package com.mazaiting.classfile.attr.info;

import com.mazaiting.classfile.ClassReader;
import com.mazaiting.classfile.attr.MemberInfo;
import com.mazaiting.classfile.attr.entity.ExceptionTableEntity;
import com.mazaiting.classfile.constant.ConstantPool;

import java.util.Arrays;

/**
 * 变长属性，只存在于method_info结构中。Code属性中存 放字节码等方法相关信息
 * max_stack给出操作数栈的最大深度，max_locals给出局部变量表大小
 * @author mazaiting
 * @since 2021/8/12
 */
public class ConstantCodeAttribute extends AttributeInfo {

    /**
     * 最大操作数栈 无符号 u2
     */
    private int maxStack;
    /**
     * 最大局部变量表 无符号 u2
     */
    private int maxLocals;
    /**
     * 方法体
     */
    private byte[] code;
    /**
     * 异常表计数 无符号 u2
     */
    private int exceptionTableCount;
    /**
     * 异常表
     */
    private ExceptionTableEntity[] exceptionTable;
    /**
     * 属性信息
     */
    private AttributeInfo[] attributeInfos;

    public ConstantCodeAttribute(ConstantPool pool, int index, int length) {
        super(pool, index, length);
    }

    @Override
    public void readInfo(ClassReader reader) {
        this.maxStack = reader.readU2ToUnsignedShort();
        this.maxLocals = reader.readU2ToUnsignedShort();
        int codeLength = reader.readU4ToInt();
        this.code = reader.readBytes(codeLength);
        this.exceptionTable = readExceptionTable(reader);
        this.attributeInfos = MemberInfo.readAttributes(reader, pool);
    }

    /**
     * 读取异常表
     * @param reader 字节码读取工具
     * @return 异常表实体
     */
    private ExceptionTableEntity[] readExceptionTable(ClassReader reader) {
        this.exceptionTableCount = reader.readU2ToUnsignedShort();
        ExceptionTableEntity[] exceptionTableEntities = new ExceptionTableEntity[exceptionTableCount];
        for (int i = 0; i < exceptionTableCount; i++) {
            exceptionTableEntities[i] = new ExceptionTableEntity(
                    reader.readU2ToUnsignedShort(),
                    reader.readU2ToUnsignedShort(),
                    reader.readU2ToUnsignedShort(),
                    reader.readU2ToUnsignedShort()
            );
        }
        return exceptionTableEntities;
    }

    @Override
    public String toString() {
        return "ConstantCodeAttribute{" +
                "maxStack=" + maxStack +
                ", maxLocals=" + maxLocals +
                ", code=" + Arrays.toString(code) +
                ", exceptionTableCount=" + exceptionTableCount +
                ", exceptionTable=" + Arrays.toString(exceptionTable) +
                ", attributeInfos=" + Arrays.toString(attributeInfos) +
                '}';
    }
}


















